package com.dingwen.treasure.business.juc;


import cn.hutool.core.thread.ThreadUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;

/**
 * 　CompletableFutureApi: CompletableFuture 案列
 * 　@author dingwen
 * 　@date 2022/7/1
 */
@Slf4j
@SuppressWarnings("ALL")
public class CompletableFutureApi {
    @SneakyThrows
    public static void main(String[] args) {
        baseApi();
    }

    /**
     * 合并结果
     *
     * @throws InterruptedException 中断异常
     * @throws ExecutionException   执行异常
     */
    public static void completable() throws InterruptedException, java.util.concurrent.ExecutionException {
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            log.info(Thread.currentThread().getName());
            ThreadUtil.sleep(100);
            return 10;
        });


        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            log.info(Thread.currentThread().getName());
            ThreadUtil.sleep(100);
            return 20;
        });

        CompletableFuture<Integer> completableFuture = future1.thenCombine(future2, (step1, step2) -> {
            return step1 + step2;
        });
        log.info("re: {}", completableFuture.get());
    }

    /**
     * 选择快速
     *
     * @throws InterruptedException 中断异常
     * @throws ExecutionException   执行异常
     */
    public static void selectFast() throws InterruptedException, java.util.concurrent.ExecutionException {
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            log.info(Thread.currentThread().getName());
            ThreadUtil.sleep(1);
            return 10;
        });


        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            log.info(Thread.currentThread().getName());
            ThreadUtil.sleep(1);
            return 20;
        });

        CompletableFuture<Integer> completableFuture = future1.applyToEither(future2, v -> {
            log.info("v: {}", v);
            return v;
        });
         Integer re = completableFuture.get();
        log.info("re: {}", re);
    }

    /**
     * 基本api
     */
    private static void baseApi() {
         ExecutorService executorService = Executors.newFixedThreadPool(2);

        //CompletableFuture<Integer> completableFuture = CompletableFuture
        CompletableFuture<Void> completableFuture = CompletableFuture
                //.runAsync()
                .supplyAsync(() -> {
                    int i = 1 / 0;
                    return 1;
                }, executorService)

                // 出异常则终止


                .thenApply(v -> {
                    return v + 1;
                })
                .thenAccept(e -> {
                    log.info("thenAccept: {}", e);
                })
                //.thenApply(v -> {
                //    int i = 1 / 0;
                //    return 100;
                //})

                // 无返回值 无入参
                .thenRun(() -> {
                    log.info("thenRun");
                })

                // 出现异常继续

                //.handle((v, e) -> {
                //    int i = 1 / 0;
                //    return v + 1;
                //})
                //.handle((v, e) -> {
                //    return 100;
                //})
                //.whenComplete((v, e) -> {
                //    log.info("v:{}", v);
                //    log.info("e:{}", e);
                //})
                //// 出现异常执行
                //.exceptionally(e -> {
                //    log.info("e:{}", e);
                //    return 6666;
                //})
                ;

        //final Integer join = completableFuture.join();
        //log.info("join:{}",join);
        //final Integer get = completableFuture.get();
        //log.info("get:{}", get);

        // 立刻获取，没有则返回默认值
        //final Integer now = completableFuture.getNow(100);
        //log.info("now:{}",now);

        //TODO 确认complete() 传参数含义
        //final boolean complete = completableFuture.complete(10);
        //log.info("complete:{}", complete);

        executorService.shutdown();
    }


}
